home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / lib / mntlib44.zoo / mntlib / _normdf.cpp < prev    next >
C/C++ Source or Header  |  1993-06-17  |  6KB  |  220 lines

  1. | mjr: not needed _normdf for -__M68881__ or the sfp004
  2. | however, _infinitydf is retained
  3.  
  4. |#######################################################################
  5.  
  6. | double floating point normalization routine
  7. |
  8. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  9. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  10. |
  11. | Revision 1.6.3 michal 05-93 (ntomczak@vm.ucs.ualberta.ca)
  12. |  + restored and ensured future synchronization with errno codes
  13. |  + removed bogus error when normalizing legitimate zero
  14. |  + small mods to shave off few cycles
  15. |
  16. | patched by Olaf Flebbe (flebbe@tat.physik.uni-tuebingen.de)
  17. |
  18. | Revision 1.6.2 olaf 12-92:
  19. |  + added support for -0.
  20. |
  21. | Revision 1.6.1 olaf 10-92:
  22. |  + corrected rounding in tie case: round up, not down.
  23. |    (needed for enquire 4.3)
  24. |
  25. | Revision 1.6, kub 04-90 :
  26. | more robust handling exponent and sign handling for 32 bit integers. There
  27. | are now overflow tests for 32 bit exponents, and bit 31 of the sign flag
  28. | is or ed to bit 15 for later checks (i.e. both bits 31 and 15 are now sign
  29. | bits). Take care, the upper 16 bits of rounding info are ignored for 32 bit
  30. | integers !
  31. |
  32. | Revision 1.5, ++jrb 03-90:
  33. | change __normdf interface to expect ints instead of shorts. easier
  34. | to interface to 32 bit int code. this file is now pre-processed,
  35. | with __MSHORT__ defined when ints are 16 bits.
  36. |
  37. | Revision 1.4, kub 03-90 :
  38. | export ___normdf entry to C language. Rename the internal entry to a name
  39. | not accessible from C to prevent crashes
  40. |
  41. | Revision 1.3, kub 01-90 :
  42. | added support for denormalized numbers
  43. |
  44. | Revision 1.2, kub 01-90 :
  45. | replace far shifts by swaps to gain speed
  46. |
  47. | Revision 1.1, kub 12-89 :
  48. | Ported over to 68k assembler
  49. |
  50. | Revision 1.0:
  51. | original 8088 code from P.S.Housel
  52.  
  53.     .text
  54.     .even
  55.     .globl    __infinitydf
  56.  
  57. #if !defined (__M68881__) && !defined (sfp004)
  58.     .globl    ___normdf
  59.     .globl    norm_df
  60. #include "errbase.h"
  61. # ifdef    ERROR_CHECK
  62. LC0:
  63.     .ascii "normdf: OVERFLOW\12\15\0"
  64.     .even
  65. # endif    ERROR_CHECK
  66.  
  67.     | C entry, for procs dealing with the internal representation :
  68.     | double __normdf(long long mant, int exp, int sign, int rbits);
  69. ___normdf:
  70.     lea    sp@(4),a0    | parameter pointer
  71.     moveml    d2-d7,sp@-    | save working registers
  72.     moveml    a0@+,d4-d5    | get mantissa
  73.  
  74. # ifdef __MSHORT__
  75.     movew    a0@+,d0        | get exponent
  76.     movew    a0@+,d2        | get sign
  77.     movew    a0@+,d1        | rounding information
  78. # else
  79.     movel    a0@+,d0        | get exponent
  80.     movel    a0@+,d2        | get sign
  81.     bpl    0f        | or bit 31 to bit 15 for later tests
  82.     bset    #15,d2
  83. 0:    movel    a0@+,d1        | rounding information
  84.  
  85.     movel    #0x7fff,d3
  86.     cmpl    d3,d0        | test exponent
  87.     bgt    oflow
  88.     notl    d3        | #-0x8000 -> d3
  89.     cmpl    d3,d0
  90.     blt    retz
  91. # endif
  92.  
  93.     | internal entry for floating point package, saves time
  94.     | d0=u.exp, d2=u.sign, d1=rounding bits, d4/d5=mantissa
  95.     | registers d2-d7 must be saved on the stack !
  96. norm_df:
  97.     movel    d4,d3        | rounding and u.mant == 0 ?
  98.     orl    d5,d3
  99.     bne    1f
  100.     tstb    d1
  101.     beq    retzok
  102. 1:
  103.     movel    d4,d3
  104.     andl    #0xfffff000,d3    | fast shift, 16 bits ?
  105.     bne    2f
  106.     cmpw    #9,d0        | shift is going to far; do normal shift
  107.     ble    2f        |  (minimize shifts here : 10l = 16l + 6r)
  108.     swap    d4        | yes, swap register halfs
  109.     swap    d5
  110.     movew    d5,d4
  111.     moveb    d1,d5        | some doubt about this one !
  112.     lslw    #8,d5
  113.     clrw    d1
  114.     subw    #16,d0        | account for swap
  115.     bra    1b
  116. 2:
  117.     clrb    d2        | sticky byte
  118.     movel    #0xffe00000,d6
  119. 3:    tstw    d0        | divide (shift)
  120.     ble    0f        |  denormalized number
  121.     movel    d4,d3
  122.     andl    d6,d3        |  or until no bits above 53
  123.     beq    4f
  124. 0:    addw    #1,d0        | increment exponent
  125.     lsrl    #1,d4
  126.     roxrl    #1,d5
  127.     orb    d1,d2        | set sticky
  128.     roxrb    #1,d1        | shift into rounding bits
  129.     bra    3b
  130. 4:
  131.     andb    #1,d2
  132.     orb    d2,d1        | make least sig bit sticky
  133.     asrl    #1,d6        | #0xfff00000 -> d6
  134. 5:    movel    d4,d3        | multiply (shift) until
  135.     andl    d6,d3        | one in implied position
  136.     bne    6f
  137.     subw    #1,d0        | decrement exponent
  138.     beq    6f        |  too small. store as denormalized number
  139.     addb    d1,d1        | some doubt about this one *
  140.     addxl    d5,d5
  141.     addxl    d4,d4
  142.     bra    5b
  143. 6:
  144.     tstb    d1        | check rounding bits
  145.     bge    8f        | round down - no action neccessary
  146.     negb    d1
  147.     bvc    7f        | round up
  148.         movew   d5,d1           | tie case - round to even
  149.                                 | dont need rounding bits any more
  150.         andw    #1,d1           | check if even
  151.         beq     8f              | mantissa is even - no action necessary
  152.                                 | fall through
  153. 7:
  154.     clrl    d1        | zero rounding bits
  155.     addl    #1,d5
  156.     addxl    d1,d4
  157.     tstw    d0
  158.     bne    0f        | renormalize if number was denormalized
  159.     addw    #1,d0        | correct exponent for denormalized numbers
  160.     bra    2b
  161. 0:    movel    d4,d3        | check for rounding overflow
  162.     asll    #1,d6        | #0xffe00000 -> d3
  163.     andl    d6,d3
  164.     bne    2b        | go back and renormalize
  165. 8:
  166.     movel    d4,d3        | check if normalization caused an underflow
  167.     orl    d5,d3
  168.     beq    retz
  169.     tstw    d0        | check for exponent overflow or underflow
  170.     blt    retz
  171.     cmpw    #2047,d0
  172.     bge    oflow
  173.  
  174.     lslw    #5,d0        | re-position exponent - one bit too high
  175.     lslw    #1,d2        | get X bit
  176.     roxrw    #1,d0        | shift it into sign position
  177.     swap    d0        | map to upper word
  178.     clrw    d0
  179.     andl    #0x0fffff,d4    | top mantissa bits
  180.     orl    d0,d4        | insert exponent and sign
  181.     movel    d4,d0
  182.     movel    d5,d1
  183.     moveml    sp@+,d2-d7
  184.     rts
  185.  
  186. retz:
  187.     moveq    #Erange,d0
  188.     Emove   d0,Errno
  189. retzok:
  190.     moveq    #0,d0        | return zero value
  191.     movel    d0,d1
  192.     lslw    #1,d2        | set value of extension
  193.     roxrl    #1,d0        | and move it to hight bit of d0
  194. 0:    moveml    sp@+,d2-d7
  195.     rts
  196.  
  197. oflow:
  198. #ifdef    ERROR_CHECK
  199.     pea    pc@(LC0)
  200.     pea    Stderr
  201.     jbsr    _fprintf    |
  202.     addql    #8,a7        |
  203.     moveq    #Erange,d0
  204.     Emove    d0,Errno
  205. #endif    ERROR_CHECK
  206.  
  207. |    moveml    pc@(__infinitydf),d0-d1 | return infinity value
  208.     moveml    __infinitydf,d0-d1 | return infinty value
  209.     tstw    d2
  210.     bpl    1f
  211.     bset    #31,d0
  212. 1:
  213.     moveml    sp@+,d2-d7    | should really cause trap ?!? (mjr: why?)
  214.     rts
  215.  
  216. #endif __M68881__
  217.  
  218. __infinitydf:            | +infinity as proposed by IEEE
  219.     .long    0x7ff00000,0x00000000
  220.